package slimgo

import (
	"fmt"
	//"net"
	"github.com/Unknwon/goconfig"
	"github.com/jesusslim/slimgo/session"
	"net/http"
	"time"
)

type App struct {
	Server     *http.Server
	Handerlers *ControllerRegister
}

func NewApp() *App {
	ctrlReg := NewControllerRegister()
	app := &App{
		Server:     &http.Server{},
		Handerlers: ctrlReg,
	}
	return app
}

func (this *App) beforeRun() {
	//Session
	if SessionOn {
		confPath := "conf/conf.ini"
		sessConfs, err := goconfig.LoadConfigFile(confPath)
		if err != nil {
			Waring("Can't find config file:conf/conf.ini ! ", err.Error())
			return
		}
		section := "session"
		sessionProvider := sessConfs.MustValue(section, "Provider")
		path := sessConfs.MustValue(section, "Path")
		cookieKey := sessConfs.MustValue(section, "CookieKey")
		domain := sessConfs.MustValue(section, "Domain")
		gcLifeTime := sessConfs.MustInt(section, "GcLifeTime")
		maxLifeTime := sessConfs.MustInt(section, "MaxLifeTime")
		cookieLifeTime := sessConfs.MustInt(section, "CookieLifeTime")
		seesionIdLength := sessConfs.MustInt(section, "SessionIdLength")
		SessionFactory, err = session.NewSessionFactory(sessionProvider, cookieKey, domain, path, gcLifeTime, maxLifeTime, cookieLifeTime, seesionIdLength)
		if err != nil {
			panic("Init session failed." + err.Error())
		}

		// RegisterHookBeforeHttpPre("session", func(ctx *context.Context) {
		// 	var err error
		// 	ctx.Input.Session, err = SessionFactory.SessionStart(ctx.Request, ctx.ResponseWriter)
		// 	if err != nil {
		// 		Error("Session start failed.", err.Error())
		// 	}
		// })

		// RegisterHookAfterHttpFinish("session_save", func(ctx *context.Context) {
		// 	ctx.Input.Session.SessionSave(ctx.ResponseWriter)
		// })
	}

	//view
	err := BuildTpl(ViewPath)
	if err != nil {
		Error("Build template failed,", err.Error())
	}

	//timetask
	for name, t := range tasks {
		if t.runtag == true {
			go t.Start()
			Logger.Info("Timetask:", name, " is running.")
		}
	}

	//hooks
	for key, f := range hooks.hookBeforeAppRun {
		err := f()
		if err != nil {
			Logger.Error("Hook:", key, " err,", err.Error())
		} else {
			Logger.Info("Hook:", key, " finished.")
		}
	}
}

func (this *App) Run() {
	this.beforeRun()
	address := HttpAddress
	if HttpPort != 0 {
		address = fmt.Sprintf("%s:%d", address, HttpPort)
	}
	var (
		err error
		//listener net.Listener
	)
	ending := make(chan bool, 1)
	//http
	this.Server.Addr = address
	this.Server.Handler = this.Handerlers
	this.Server.ReadTimeout = time.Duration(HttpServerTimeOut) * time.Second
	this.Server.WriteTimeout = time.Duration(HttpServerTimeOut) * time.Second
	Logger.Info("Http running on ", this.Server.Addr)
	go func() {
		err = this.Server.ListenAndServe()
		if err != nil {
			Logger.Error(err.Error())
			time.Sleep(100 * time.Microsecond)
			ending <- true
		}
	}()
	<-ending
}
